package com.firstsource.networking.ip.tracker.util;

import java.util.LinkedList;
import java.util.List;
import org.zkoss.lang.Threads;
import org.zkoss.util.logging.Log;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Desktop;
import org.zkoss.zk.ui.DesktopUnavailableException;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.UiException;
import org.zkoss.zul.Label;

public class DeviceSession extends Thread {

	private static final Log log = Log.lookup(DeviceSession.class) ;

	private boolean _ceased;

	private DeviceConsole device = null ;

	private final Desktop desktop ;

	private Component console ;

	private String name ;

	private List<String> msgs ;

	public DeviceSession(DeviceConsole currentConsole, String deviceName, Component newConsole) {
		device = currentConsole ;
		name = deviceName ;
		console = newConsole ;
		desktop = console.getDesktop() ;
		msgs = new LinkedList<String>() ;
	}

	
	/**
	 * send new messages to UI if necessay
	 */
	public void run() {
		if (!desktop.isServerPushEnabled()) 
			desktop.enableServerPush(true);
		log.info("active chatter : " + getName());
		device.subscribe(this);
		try {
			while (!_ceased) {
				try {
					if (msgs.isEmpty()) {
						Threads.sleep(20);// Update each 0.5 seconds
					} else {
						Executions.activate(desktop);
						try {
							process();
						} finally {
							Executions.deactivate(desktop);
						}
					}
				} catch (DesktopUnavailableException ex) {
					throw ex;
				} catch (Throwable ex) {
					log.error(ex);
					throw UiException.Aide.wrap(ex);
				}
			}
		} finally {
			log.info(getName() + " logout the chatroom!");
			device.unsubscribe(this);			
			if (desktop.isServerPushEnabled())
				Executions.getCurrent().getDesktop().enableServerPush(false);
		}
		log.info("The device console thread ceased: " + getName() );
	}

	/**
	 * return sender's name
	 * 
	 * @return
	 */
	public String getSender() {
		return name;
	}

	/**
	 * add message to this chatter
	 * 
	 * @param message
	 */
	public void addMessage(String message) {
		msgs.add(message);
	}

	/**
	 * send message to others
	 * 
	 * @param message
	 */
	public void sendMessage(String message) {
		device.broadcast(getSender(), message);
	}

	private void renderMessages() {
		while (!msgs.isEmpty()) {
			String msg;
			synchronized (msgs) {
				msg = msgs.remove(0);
			}
			console.appendChild(new Label(msg));
		}
	}

	private void process() throws Exception {
		renderMessages();
	}

	/**
	 * stop this thread
	 * 
	 */
	public void setDone() {
		_ceased = true;
	}
}
